import request, { extend } from 'umi-request';
import URI from 'urijs';
import { notification } from 'antd';
import router from 'umi/router';
import settings from '@/settings';
import Dialog from '@/components/Dialog';
import { formatUrl } from '@/utils';

const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  405: '方法不被允许。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。',
};
// const errorHandler = error => {
// 	const { response={} } = error
// 	const errortext = codeMessage[response.status] || response.statusText
// 	const { status, url } = response

// 	if (status === 401) {
// 		notification.error({
// 			message: '未登录或登录已过期，请重新登录。'
// 		})
// 		return
// 	}
// 	notification.error({
// 		message: `请求错误 ${status}: ${url}`,
//     	description: errortext
// 	})
// }
export const errorHandler = error => {
  const { response = {} } = error;
  const { status, url } = response;

  if (!error) {
    const errorMessage = '服务器发生异常';

    notification.error({
      message: errorMessage,
    });
    return {
      code: 0,
      message: errorMessage,
    };
  }
  const { code = status, message } = error;
  const errortext = codeMessage[code];

  if (code === 401) {
    Dialog.destroyAll();
    notification.error({
      message: '未登录或登录已过期，请重新登录。',
    });
    router.replace('/login');
    return {
      code,
      message: '登录超时',
    };
  }
  if (errortext) {
    let _message = [`${code}错误：${errortext}`];
    if (url) {
      _message = [..._message, `错误请求: ${url}`];
    }
    notification.error({
      message: message === 'http error' ? _message.join('\n') : message,
    });

    // 多次push会出警告（Hash history cannot PUSH the same path; a new entry will not be added to the history stack）
    // push会发生上面的警告，用replace即可修复
    // if (status === 403) {
    //   router.replace('/exception/403');
    // }
    // if (status <= 504 && status >= 500) {
    //   router.replace('/exception/500');
    // }
    return {
      code,
      message: errortext,
    };
  }
  if (code !== 200) {
    notification.error({
      message: message || '未知异常',
    });
  }
  return {
    code,
    message,
  };
};

request.interceptors.response.use(async (response, options) => {
  const data = await response
    .clone()
    .json()
    .catch(e => {
      if (response.status === 200) {
        notification.error({
          message: '不正确的返回格式',
        });
      }
    });
  if (data != null) {
    if (typeof data !== 'object' || (!options.type && data.code == null)) {
      if (response.status === 200) {
        notification.error({
          message: '不正确的返回格式',
        });
        return;
      }
    } else if (!options.type && data.code !== settings.code) {
      return Promise.reject(data);
    }
  }
  return response;
});

const _request = (url, options) => {
  if (options) {
    url = formatUrl(url, options.data || options.params)
  }

  var uri = new URI(url);
  url = uri
    .search({
      ...uri.search(true),
      temp: new Date().getTime(),
    })
    .normalize()
    .toString();

  return extend({
    errorHandler,
    prefix: settings.prefix,
    // requestType: 'form',
    credentials: 'include',
  })(url, options); /*.then((r = {}) => r.data)*/
};

_request.post = (url, options) => {
  return _request(url, {
    ...options,
    method: 'POST',
  });
};

_request.put = (url, options) => {
  return _request(url, {
    ...options,
    method: 'PUT',
  });
};

/**
 * 后置处理结果（去除code验证包装后的纯结果集）
 * 通用方法（底层调用 umi-request 二次包装的 fetch）
 * 示例：
 * await $request(url, {
 *   method: 'post',
 *   data: {
 *     id: 1
 *   }
 * })
 *
 * 已统一拦截异常，见顶部异常码
 */
// export const $request = (url, options) => {
//   return new Promise((resolve, reject) => {
//     _request(url, {
//       ...options,
//     }).then(({ code, data = {} }) => {
//       if (code === settings.code) {
//         resolve(data);
//       } else {
//         reject(data);
//       }
//     });
//   });
// };

export const $request = async (url, options) => {
  const { code, data = {} } = await _request(url, {
      ...options,
    })
  if (code === settings.code) {
    return data;
  } else {
    Promise.reject(data).catch(e => {

    });
  }
};

$request.post = (url, options) => {
  return $request(url, {
    ...options,
    method: 'POST',
  });
};

$request.put = (url, options) => {
  return $request(url, {
    ...options,
    method: 'PUT',
  });
};

/**
 * 交由前置处理异常提示
 * 示例：
 * const { code, message } = await $http(url, {
 *   method: 'post',
 *   data: {
 *     id: 1
 *   }
 * })
 *
 * code = 200 为成功状态
 * message 后台返回的错误消息
 */
export const $http = (url, options) => {
  return _request(url, {
    ...options,
    errorHandler: error => {
      const { response = {} } = error;
      const { status } = response;
      const { code = status, message = '发生异常' } = error;
      return {
        code,
        message,
      };
    },
  });
};

/**
 * 包装方法（post）
 */
$http.post = (url, options) => {
  return $http(url, {
    ...options,
    method: 'POST',
  });
};

/**
 * 包装方法（put）
 */
$http.put = (url, options) => {
  return $http(url, {
    ...options,
    method: 'PUT',
  });
};

export default _request;
